package platform.util;

import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
import com.opensymphony.xwork2.interceptor.ExceptionHolder;
import com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor;
/***
 * 拦截器动态的创建Form对象
 * @author ZhangYQ
 * 2009-3-10
 */
public class MyExceptionInterceptor extends ExceptionMappingInterceptor{

	private static final long serialVersionUID = 1L;

	protected static final Log log = LogFactory.getLog(MyExceptionInterceptor.class);

	    protected Log categoryLogger;
	    protected boolean logEnabled = false;
	    protected String logCategory;
	    protected String logLevel;


	    public boolean isLogEnabled() {
	        return logEnabled;
	    }

	    public void setLogEnabled(boolean logEnabled) {
	        this.logEnabled = logEnabled;
	    }

	    public String getLogCategory() {
			return logCategory;
		}

		public void setLogCategory(String logCatgory) {
			this.logCategory = logCatgory;
		}

		public String getLogLevel() {
			return logLevel;
		}

		public void setLogLevel(String logLevel) {
			this.logLevel = logLevel;
		}

	    /*public String intercept(ActionInvocation invocation) throws Exception {
	        String result;
	        BaseAction ba = (BaseAction)invocation.getAction();
	        try {
	            result = invocation.invoke();
	        } catch (Exception e) {
	        	e.printStackTrace();
	        	StackTraceElement a[] = e.getStackTrace();
	        	StringBuffer sbException = new StringBuffer();
	        	log.info("---------------------------------------------------------");
	        	log.info(e);
	        	for(int i = 0 ; i < a.length ; i ++){
	        		if(a[i].getClassName().startsWith("aero")){
		        		sbException.append("       "+a[i].getClassName()+".");
		        		sbException.append(""+a[i].getMethodName()+"");
		        		sbException.append("("+a[i].getLineNumber()+")");
		        		sbException.append("\n");
	        		}
	        	}
	        	log.info(sbException);
	        	log.info("以上异常发生于-----"+Util.getDate());
	        	log.info("----------------------------------------------------------");
	            if (logEnabled) {
	                handleLogging(e);
	            }
	            List exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
	            String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
	            if (mappedResult != null) {
	            	String exceptionMessage = "";
	            	if(e.getMessage()!=null){
	            		exceptionMessage = e.getMessage();
	            		ba.getAjaxMessagesJson().setMessage("6", exceptionMessage,exceptionMessage);
	            	}else{
	            		if(e instanceof NullPointerException){
		            		ba.getAjaxMessagesJson().setMessage("1", Util.getR("baseaction.error.exception.NullPointerException", "base"),e.toString());
		            	}else if(e instanceof ClassCastException){
		            		ba.getAjaxMessagesJson().setMessage("2", Util.getR("baseaction.error.exception.ClassCastException", "base"),e.toString());
		            	}else if(e instanceof ClassNotFoundException){
		            		ba.getAjaxMessagesJson().setMessage("3", Util.getR("baseaction.error.exception.ClassNotFoundException", "base"),e.toString());
		            	}else if(e instanceof RuntimeException){
		            		ba.getAjaxMessagesJson().setMessage("4", Util.getR("baseaction.error.exception.RuntimeException", "base"),e.toString());
		            	}else {
		            		ba.getAjaxMessagesJson().setMessage("5", Util.getR("baseaction.error.exception.SystemException", "base"),e.toString());
		            	}
	            	}
	                result = mappedResult;
	                publishException(invocation, new ExceptionHolder(e));
	            } else {
	                throw e;
	            }
	        }

	        return result;
	    }
*/
	    /**
	     * Handles the logging of the exception.
	     *
	     * @param e  the exception to log.
	     */
	    protected void handleLogging(Exception e) {
	    	if (logCategory != null) {
	        	if (categoryLogger == null) {
	        		// init category logger
	        		categoryLogger = LogFactory.getLog(logCategory);
	        	}
	        	doLog(categoryLogger, e);
	    	} else {
	    		doLog(log, e);
	    	}
	    }

	    /**
	     * Performs the actual logging.
	     *
	     * @param logger  the provided logger to use.
	     * @param e  the exception to log.
	     */
	    protected void doLog(Log logger, Exception e) {
	    	if (logLevel == null) {
	    		logger.debug(e.getMessage(), e);
	    		return;
	    	}

	    	if ("trace".equalsIgnoreCase(logLevel)) {
	    		logger.trace(e.getMessage(), e);
	    	} else if ("debug".equalsIgnoreCase(logLevel)) {
	    		logger.debug(e.getMessage(), e);
	    	} else if ("info".equalsIgnoreCase(logLevel)) {
	    		logger.info(e.getMessage(), e);
	    	} else if ("warn".equalsIgnoreCase(logLevel)) {
	    		logger.warn(e.getMessage(), e);
	    	} else if ("error".equalsIgnoreCase(logLevel)) {
	    		logger.error(e.getMessage(), e);
	    	} else if ("fatal".equalsIgnoreCase(logLevel)) {
	    		logger.fatal(e.getMessage(), e);
	    	} else {
	    		throw new IllegalArgumentException("LogLevel [" + logLevel + "] is not supported");
	    	}
	    }

//	    private String findResultFromExceptions(List exceptionMappings, Throwable t) {
//	        String result = null;
//
//	        // Check for specific exception mappings.
//	        if (exceptionMappings != null) {
//	            int deepest = Integer.MAX_VALUE;
//	            for (Iterator iter = exceptionMappings.iterator(); iter.hasNext();) {
//	                ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) iter.next();
//	                int depth = getDepth(exceptionMappingConfig.getExceptionClassName(), t);
//	                if (depth >= 0 && depth < deepest) {
//	                    deepest = depth;
//	                    result = exceptionMappingConfig.getResult();
//	                }
//	            }
//	        }
//
//	        return result;
//	    }

	    /**
	     * Return the depth to the superclass matching. 0 means ex matches exactly. Returns -1 if there's no match.
	     * Otherwise, returns depth. Lowest depth wins.
	     *
	     * @param exceptionMapping  the mapping classname
	     * @param t  the cause
	     * @return the depth, if not found -1 is returned.
	     */
	    public int getDepth(String exceptionMapping, Throwable t) {
	        return getDepth(exceptionMapping, t.getClass(), 0);
	    }

	    private int getDepth(String exceptionMapping, Class exceptionClass, int depth) {
	        if (exceptionClass.getName().indexOf(exceptionMapping) != -1) {
	            // Found it!
	            return depth;
	        }
	        // If we've gone as far as we can go and haven't found it...
	        if (exceptionClass.equals(Throwable.class)) {
	            return -1;
	        }
	        return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1);
	    }

	    /**
	     * Default implementation to handle ExceptionHolder publishing. Pushes given ExceptionHolder on the stack.
	     * Subclasses may override this to customize publishing.
	     *
	     * @param invocation The invocation to publish Exception for.
	     * @param exceptionHolder The exceptionHolder wrapping the Exception to publish.
	     */
	    protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) {
	        invocation.getStack().push(exceptionHolder);
	    }
}
